package cn.xinfei.xdecision.common.service.datax.datainterface.v2.impl;


import cn.xinfei.xdecision.common.dao.datax.datainterface.v2.VarInterfaceInfoMapper;
import cn.xinfei.xdecision.common.dao.datax.datainterface.v2.VariableInterfaceMapper;

import cn.xinfei.xdecision.common.model.common.requestParam.QueryListParam;
import cn.xinfei.xdecision.common.model.datax.datainterface.v2.VarInterfaceInfo;
import cn.xinfei.xdecision.common.model.datax.datainterface.v2.VariableInterface;
import cn.xinfei.xdecision.common.model.datax.datamanage.v2.Variable;
import cn.xinfei.xdecision.common.model.login.SSOUser;
import cn.xinfei.xdecision.common.model.login.SessionManager;
import cn.xinfei.xdecision.common.service.datax.datainterface.v2.VarInterfaceInfoService;
import cn.xinfei.xdecision.common.utils.exception.ApiException;
import cn.xinfei.xdecision.common.utils.exception.enums.ErrorCodeEnum;
import com.alibaba.fastjson.JSONObject;
import com.baomidou.mybatisplus.core.conditions.Wrapper;
import com.baomidou.mybatisplus.core.conditions.query.LambdaQueryWrapper;
import com.baomidou.mybatisplus.core.conditions.query.QueryWrapper;
import com.baomidou.mybatisplus.extension.conditions.query.LambdaQueryChainWrapper;
import com.baomidou.mybatisplus.extension.service.impl.ServiceImpl;
import com.github.pagehelper.PageHelper;
import com.github.pagehelper.PageInfo;
import com.google.common.collect.Maps;
import org.apache.commons.lang3.StringUtils;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Transactional;
import org.springframework.util.CollectionUtils;

import javax.annotation.Resource;
import java.util.*;
import java.util.stream.Collectors;

@Service
public class VarInterfaceInfoServiceImpl extends ServiceImpl<VarInterfaceInfoMapper, VarInterfaceInfo> implements VarInterfaceInfoService {

    private final Logger LOGGER = LoggerFactory.getLogger(this.getClass());

    @Resource
    VarInterfaceInfoMapper varInterfaceInfoMapper;

    @Resource
    VariableInterfaceMapper variableInterfaceMapper;


    @Override
    public Map<String, List<String>> selectChargedApiAndVarsByVarCodes(Collection<String> varCodes) {

        if (CollectionUtils.isEmpty(varCodes)) {
            return Collections.emptyMap();
        }
        List<Long> chargedDataSourceList =
                variableInterfaceMapper
                        .selectDatasourceIdsByVariableCodes(varCodes)
                        .stream()
                        .filter(item -> {
                            Boolean isCharged = varInterfaceInfoMapper.selectIsChargeById(item.intValue());
                            return Objects.isNull(isCharged) || isCharged;
                        })
                        .distinct()
                        .collect(Collectors.toList());

        return getApiAndVarsFromFeeAttrDataSources(varCodes, chargedDataSourceList);
    }


    @Override
    public Map<String, List<String>> getApiAndVarsFromFeeAttrDataSources(Collection<String> varCodes, List<Long> dataSourceList) {

        if (CollectionUtils.isEmpty(dataSourceList)) {
            return Collections.emptyMap();
        }

        List<String> apiList = Optional.of(dataSourceList).orElse(Collections.emptyList())
                .stream().map(item -> variableInterfaceMapper
                        .searchAllByDatasourceId(item.intValue()))
                .map(item -> item.stream()
                        .map(VariableInterface::getApi).collect(Collectors.toList()))
                .flatMap(Collection::stream)
                .distinct()
                .collect(Collectors.toList());

        Map<String, List<String>> apiAndVarMap = Maps.newHashMap();
        if (CollectionUtils.isEmpty(apiList)) {
            LOGGER.info("varCodes: {}, apiList is empty", JSONObject.toJSONString(varCodes));
            return apiAndVarMap;
        }
        LOGGER.info("varCodes: {}, dataSourceList: {},apiList: {}",
                JSONObject.toJSONString(varCodes),
                JSONObject.toJSONString(dataSourceList),
                JSONObject.toJSONString(apiList));

        apiList.forEach(item -> {
            List<String> varCodeList = variableInterfaceMapper.searchVariableCodesByApi(item)
                    .stream()
                    .map(VariableInterface::getVariableCode)
                    .filter(varCodes::contains)
                    .collect(Collectors.toList());
            apiAndVarMap.put(item, varCodeList);
        });
        return apiAndVarMap;
    }

    @Override
    public Map<String, List<String>> selectFreeApiAndVarsByVarCodes(Collection<String> varCodes) {

        if (CollectionUtils.isEmpty(varCodes)) {
            return Collections.emptyMap();
        }

        List<Long> freeDataSourceList =
                variableInterfaceMapper
                        .selectDatasourceIdsByVariableCodes(varCodes)
                        .stream()
                        .distinct()
                        .filter(item -> {
                            Boolean isCharged = varInterfaceInfoMapper.selectIsChargeById(item.intValue());
                            return Objects.isNull(isCharged) || !isCharged;
                        })
                        .collect(Collectors.toList());

        return getApiAndVarsFromFeeAttrDataSources(varCodes, freeDataSourceList);
    }

    @Override
    public Map<String, List<String>> selectAllApiAndVarsByVarCodes(Collection<String> varCodes) {
        if (CollectionUtils.isEmpty(varCodes)) {
            return Collections.emptyMap();
        }

        List<Long> freeDataSourceList =
                new ArrayList<>(variableInterfaceMapper
                        .selectDatasourceIdsByVariableCodes(varCodes));

        return getApiAndVarsFromFeeAttrDataSources(varCodes, freeDataSourceList);
    }

    @Override
    public Map<String, List<String>> selectAllApiAndVarsByVarCodes() {
        return null;
    }

    @Override
    public VarInterfaceInfo selectInterfaceById(Long id) {
        QueryWrapper<VarInterfaceInfo> queryWrapper = new QueryWrapper<>();
        queryWrapper.eq("id", id);
        return varInterfaceInfoMapper.selectOne(queryWrapper);
    }

    @Override
    public List<VarInterfaceInfo> SelectAllInterface() {
        List<VarInterfaceInfo> varInterfaceInfoList = new LambdaQueryChainWrapper<>(varInterfaceInfoMapper)
                .select()
                .eq(VarInterfaceInfo::getStatus, 1)
                .list();
        return new ArrayList<>(Optional.ofNullable(varInterfaceInfoList)
                .orElseGet(Collections::emptyList));
    }

    @Override
    public List<Long> selectVirtualDataSourceIdsByIds(Collection<Long> ids) {

        if (CollectionUtils.isEmpty(ids)) {
            return Collections.emptyList();
        }
        return varInterfaceInfoMapper.selectVirtualDataSourceIdsByIds(ids);
    }

    @Override
    public List<String> selectTypesByIds(Collection<Long> ids) {

        if (CollectionUtils.isEmpty(ids)) {
            return Collections.emptyList();
        }
        return varInterfaceInfoMapper.selectTypesByIds(ids);
    }


    @Override
    public VarInterfaceInfo insert(VarInterfaceInfo interfaceVo) {

        Long organId = SessionManager.getLoginAccount().getOrganId();
        String userName = SessionManager.getLoginAccount().getName();
        //设置创建者和修改者
        interfaceVo.setCreator(userName);
        interfaceVo.setModifier(userName);
        interfaceVo.setOrganId(organId);
        interfaceVo.setStatus(1);
        //插入并获取insert后实体对象返回id
        boolean save = this.save(interfaceVo);
        if (!save) {
            throw new ApiException(
                    ErrorCodeEnum.INTERFACE_SAVE_ERROR.getCode(),
                    ErrorCodeEnum.INTERFACE_SAVE_ERROR.getMessage()
            );
        }
        return interfaceVo;
    }


    @Override
    public VarInterfaceInfo update(VarInterfaceInfo interfaceVo) {
        String userName = SessionManager.getLoginAccount().getName();
        //设置修改者
        interfaceVo.setModifier(userName);
        varInterfaceInfoMapper.updateById(interfaceVo);
        return interfaceVo;
    }


    @Transactional(rollbackFor = Exception.class)
    @Override
    public boolean updateStatus(Long id, Integer status) {
        return varInterfaceInfoMapper.updateStatus(id, status) > 0;
    }

    @Override
    public boolean deleteByPrimaryKey(VarInterfaceInfo interfaceVo) {
        return varInterfaceInfoMapper.deleteById(interfaceVo.getId()) > 0;
    }

    @Override
    public PageInfo queryByEntity(QueryListParam<VarInterfaceInfo> interfaceListParam) {
        VarInterfaceInfo interfaceInfo = interfaceListParam.getEntity();
        Integer pageNo = interfaceListParam.getPageNum();
        Integer pageSize = interfaceListParam.getPageSize();
        if (pageNo > 0 && pageSize > 0) {
            PageHelper.startPage(pageNo, pageSize);
        }
        Wrapper<VarInterfaceInfo> wrapper = createWrapper(interfaceInfo);
        List<VarInterfaceInfo> interfaceList = varInterfaceInfoMapper.selectList(wrapper);
        PageInfo pageInfo = new PageInfo(interfaceList);
        //  级联操作完成拼装
        List<VarInterfaceInfo> interfaceVos = new ArrayList<>();
        SSOUser sysUser = SessionManager.getLoginAccount();
        for (VarInterfaceInfo info : interfaceList) {
//            BeanUtils.copyProperties(info, interfaceVo);

//            //设置创建者昵称
            info.setCreator(sysUser.getName());
//            //设置修改者昵称
            info.setModifier(sysUser.getName());
            interfaceVos.add(info);
        }
        pageInfo.setList(interfaceVos);


        return pageInfo;
    }

    @Override
    public List<VarInterfaceInfo> getInterfaceList(Long organId) {
        return varInterfaceInfoMapper.getInterfaceList(organId);
    }


    //创建查询器
    private Wrapper<VarInterfaceInfo> createWrapper(VarInterfaceInfo query) {
        LambdaQueryWrapper<VarInterfaceInfo> wrapper = new LambdaQueryWrapper<>();
        if (query != null) {
            if (StringUtils.isNotBlank(query.getName())) {
                wrapper.like(VarInterfaceInfo::getName, query.getName());
            }
            if (StringUtils.isNotBlank(query.getMethod())) {
                wrapper.eq(VarInterfaceInfo::getMethod, query.getMethod());
            }
            if (StringUtils.isNotBlank(query.getUrl())) {
                wrapper.eq(VarInterfaceInfo::getUrl, query.getUrl());
            }
            if (query.getStatus() != null) {
                wrapper.eq(VarInterfaceInfo::getStatus, query.getStatus());
            } else {
                wrapper.ne(VarInterfaceInfo::getStatus, -1);
            }
        } else {
            wrapper.ne(VarInterfaceInfo::getStatus, -1);
        }
        wrapper.orderByDesc(VarInterfaceInfo::getId);
        return wrapper;
    }

}
